package models;

import play.*;
import play.db.jpa.*;
import play.db.jpa.Blob;

import javax.persistence.*;
import java.util.*;

@Entity(name="User")
public class User extends Model {
	
	@Column(unique=true)
	public String email;
	
	public String password;
	
	public Date regDate;
	
	public String company;

	@ManyToMany(mappedBy="friends")
	public Set<User> beFriendOf;
	
	@ManyToMany
	public Set<User> friends;
	
	@ManyToMany(mappedBy="members")
	public Set<Circle> circles;
	
	
	public Blob photo;	// 180
	public Blob photoThumbnail;	// 50
	public Blob photoTmp;
	public Blob photoTmpThumbnail;
	
	public String firstName;
	public String lastName;
	
	public User(String email, String password) {
		this.email = email;
		this.password = password;
		this.regDate = new Date();
		friends = new HashSet<User>();
		beFriendOf = new HashSet<User>();
	}
	
	public String getRepresName() {
		if(this.firstName == null && this.lastName == null) {
			int i = this.email.indexOf("@");
			if(i > 0) {
				return this.email.substring(0, i);
			} else {
				return this.email;
			}
		} else if(this.firstName == null) {
			return this.lastName;
		} else if(this.lastName == null) {
			return this.firstName;
		} else {
			return this.firstName + " " + lastName;
		}
	}
	
	public List<Post> getPosts() {
		List<Post> posts = Post.find("author=? order by postDate desc", this).fetch();
		return posts;
	}
	
	public static User connect(String email, String password) {
	    return find("byEmailAndPassword", email, password).first();
	}
	
	public static boolean emailExists(String email) {
		boolean result = User.find("byEmail", email).fetch().size() != 0;
		return result;
	}
	
	public boolean addFriend(User u) {
		if(friends.add(u)) {
			if(u.beFriendOf.add(this)) {
				this.save();
				u.save();
				return true;
			}
		}
		return false;
	}
	
	public boolean deleteFriend(User u) {
		if(friends.remove(u)) {
			if(u.beFriendOf.remove(this)) {
				this.save();
				u.save();
				return true;
			}
		}
		return false;
	}
	
	public boolean hasFriend(User u) {
		if(friends.contains(u)) {
			return true;
		}
		else {
			return false;
		}
	}
	
	public boolean isFriendOf(User u) {
		if(beFriendOf.contains(u)) {
			return true;
		}
		else {
			return false;
		}
	}
	
	public Set<User> getFriendsNotFriendOf() {
		Iterator i = friends.iterator();
		Set<User> result = new HashSet<User>();
		while(i.hasNext()) {
			User element = (User)i.next();
			if(!this.isFriendOf(element)) {
				result.add(element);
			}
		}
		return result;
	}
	
	public Set<User> getFriendOfNotFriend() {
		Iterator i = beFriendOf.iterator();
		Set<User> result = new HashSet<User>();
		while(i.hasNext()) {
			User element = (User)i.next();
			if(!this.hasFriend(element)) {
				result.add(element);
			}
		}
		return result;
	}
	
	public Set<User> getFriendsAndFriendOf() {
		Iterator i = friends.iterator();
		Set<User> result = new HashSet<User>();
		while(i.hasNext()) {
			User element = (User)i.next();
			if(this.isFriendOf(element)) {
				result.add(element);
			}
		}
		return result;
	}
	
	public Set<User> getFriends(int type) {
		switch(type) {
			case 0:	// mutual
				return this.getFriendsAndFriendOf();
			case 1:	// means he/she added me but I didn't add them
				return this.getFriendOfNotFriend();
			case 2:	// I add him/her but no response
				return this.getFriendsNotFriendOf();
			default:
				return this.getFriendsAndFriendOf();
		}
	}
	
	public int getFriendsNum() {
		return this.friends.size();
	}
	
	public boolean hasPhoto() {
		if(this.photo != null) {
			if(this.photo.exists()) {
				return true;
			}
		}
		return false;
	}
	
	public boolean hasPhotoThumbnail() {
		if(this.photoThumbnail != null) {
			if(this.photoThumbnail.exists()) {
				return true;
			}
		}
		return false;
	}
	
	public boolean hasPhotoTmp() {
		if(this.photoTmp != null) {
			if(this.photoTmp.exists()) {
				return true;
			}
		}
		return false;
	}
	
	public boolean hasPhotoTmpThumbnail() {
		if(this.photoTmpThumbnail != null) {
			if(this.photoTmpThumbnail.exists()) {
				return true;
			}
		}
		return false;
	}
	
	public boolean distroyPhoto() {
		if(this.hasPhoto()) {
			return this.photo.getFile().delete();
		}
		if(this.hasPhotoThumbnail()) {
			return this.photoThumbnail.getFile().delete();
		}
		return true;
	}
	
	public boolean distroyPhotoTmp() {
		if(this.hasPhotoTmp()) {
			return this.photoTmp.getFile().delete();
		}
		if(this.hasPhotoTmpThumbnail()) {
			return this.photoTmpThumbnail.getFile().delete();
		}
		return true;
	}
	
	public boolean inCircle(Circle c) {
//		System.out.println("examing cid="+c.id);
//		System.out.println("circles is " + circles.toString());
		if(circles.contains(c)) {
			return true;
		}
		return false;
	}
	
	public boolean joinCircle(Long cid) {
		Circle c = Circle.findById(cid);
		if (c != null) {
			if(this.circles.add(c)) {
				if(c.members.add(this)) {
					this.save();
					c.save();
					return true;
				}
			}
		}
		return false;
	}
	
	public boolean leaveCircle(Circle c) {
		if(circles.remove(c)) {
			if(c.members.remove(this)) {
				this.save();
				c.save();
				return true;
			}
		}
		return false;
	}
	
	public int getCirclesNum() {
		if(this.circles != null) {
			return this.circles.size();
		} else {
			return 0;
		}
		
	}
	
}

